import {
  Injectable,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import { Order } from '../../entities/order.entity';
import { OrderItem } from '../../entities/order-item.entity';
import { Product } from '../../entities/product.entity';
import { User } from '../../entities/user.entity';
import dayjs from 'dayjs';

/**
 * 订单服务
 */
@Injectable()
export class OrderService {
  constructor(
    @InjectRepository(Order)
    private readonly orderRepository: Repository<Order>,

    @InjectRepository(OrderItem)
    private readonly orderItemRepository: Repository<OrderItem>,

    @InjectRepository(Product)
    private readonly productRepository: Repository<Product>,

    private readonly dataSource: DataSource,
  ) {}

  /**
   * 创建订单
   *
   * 步骤：
   * 1. 验证商品存在且有效
   * 2. 计算订单金额（考虑会员折扣）
   * 3. 生成订单号
   * 4. 创建订单和订单明细
   * 5. 设置订单过期时间
   */
  async create(
    userId: string,
    createOrderDto: {
      productId?: number;
      membershipLevel?: 'vip' | 'svip';
      membershipMonths?: number;
      couponCode?: string;
    },
  ): Promise<Order> {
    const { productId, membershipLevel, membershipMonths, couponCode } =
      createOrderDto;

    // 使用事务确保数据一致性
    return await this.dataSource.transaction(async (manager) => {
      // 1. 判断订单类型
      const type = productId ? 'product' : 'membership';

      let totalAmount = 0;
      let discountAmount = 0;
      let actualAmount = 0;
      const orderItems: OrderItem[] = [];

      // 2. 获取用户信息（用于计算会员折扣）
      const user = await manager.findOne(User, { where: { id: userId } });

      if (!user) {
        throw new NotFoundException('用户不存在');
      }

      if (type === 'product') {
        // 商品订单
        const product = await manager.findOne(Product, {
          where: { id: productId?.toString() },
        });

        if (!product) {
          throw new NotFoundException('商品不存在');
        }

        if (product.status !== 'published') {
          throw new BadRequestException('商品未发布');
        }

        // 检查会员等级限制
        if (
          product.minMembership === 'vip' &&
          user.membershipLevel === 'free'
        ) {
          throw new BadRequestException('此商品需要VIP会员才能购买');
        }

        if (
          product.minMembership === 'svip' &&
          user.membershipLevel !== 'svip'
        ) {
          throw new BadRequestException('此商品需要SVIP会员才能购买');
        }

        // 计算价格（根据用户会员等级）
        let price = product.price;
        if (user.membershipLevel === 'vip' && product.vipPrice) {
          price = product.vipPrice;
          discountAmount = product.price - price;
        } else if (user.membershipLevel === 'svip' && product.svipPrice) {
          price = product.svipPrice;
          discountAmount = product.price - price;
        }

        // 如果有促销价，且促销价更低
        if (product.salePrice && product.salePrice < price) {
          const saleDiscount = price - product.salePrice;
          discountAmount += saleDiscount;
          price = product.salePrice;
        }

        totalAmount = product.price;
        actualAmount = price;

        // 创建订单明细
        const orderItem = manager.create(OrderItem, {
          productId: product.id,
          productName: product.title,
          productCover: product.cover,
          originalPrice: product.price,
          actualPrice: price,
          quantity: 1,
        });

        orderItems.push(orderItem);
      } else if (type === 'membership') {
        // 会员订单
        if (!membershipLevel || !membershipMonths) {
          throw new BadRequestException('会员等级和月数不能为空');
        }

        // 会员价格表（示例，实际应该从配置或数据库读取）
        const membershipPrices = {
          vip: { 1: 29, 3: 79, 6: 149, 12: 269 },
          svip: { 1: 49, 3: 129, 6: 239, 12: 449 },
        };

        if (!membershipPrices[membershipLevel][membershipMonths]) {
          throw new BadRequestException('无效的会员套餐');
        }

        totalAmount = membershipPrices[membershipLevel][membershipMonths];
        actualAmount = totalAmount;

        // 创建订单明细
        const orderItem = manager.create(OrderItem, {
          membershipLevel,
          membershipMonths,
          productName: `${membershipLevel.toUpperCase()} 会员 ${membershipMonths} 个月`,
          originalPrice: totalAmount,
          actualPrice: actualAmount,
          quantity: 1,
        });

        orderItems.push(orderItem);
      }

      // 3. 应用优惠券（如果有）
      if (couponCode) {
        // TODO: 实现优惠券逻辑
        // const couponDiscount = await this.applyCoupon(couponCode, userId, actualAmount);
        // discountAmount += couponDiscount;
        // actualAmount -= couponDiscount;
      }

      // 4. 生成订单号
      const orderNo = this.generateOrderNo(userId);

      // 5. 创建订单
      const order = manager.create(Order, {
        orderNo,
        userId,
        type,
        totalAmount,
        discountAmount,
        actualAmount,
        status: 'pending',
        expireAt: dayjs().add(30, 'minute').toDate(), // 30分钟后过期
      });

      const savedOrder = await manager.save(Order, order);

      // 6. 保存订单明细
      for (const item of orderItems) {
        item.orderId = savedOrder.id;
        await manager.save(OrderItem, item);
      }

      // 7. 关联查询返回完整订单
      const fullOrder = await manager.findOne(Order, {
        where: { id: savedOrder.id },
        relations: ['items', 'user'],
      });

      if (!fullOrder) {
        throw new Error('订单创建失败');
      }

      return fullOrder;
    });
  }

  /**
   * 生成订单号
   * 格式：ORDER + 时间戳(14位) + 用户ID后6位 + 随机数(6位)
   */
  private generateOrderNo(userId: string): string {
    const timestamp = dayjs().format('YYYYMMDDHHmmss');
    const userIdSuffix = userId.toString().slice(-6).padStart(6, '0');
    const random = Math.random().toString(36).substring(2, 8).toUpperCase();

    return `ORDER${timestamp}${userIdSuffix}${random}`;
  }

  /**
   * 查询用户的订单列表
   */
  async findByUserId(
    userId: string,
    page: number = 1,
    limit: number = 10,
  ): Promise<{ items: Order[]; total: number }> {
    const [items, total] = await this.orderRepository.findAndCount({
      where: { userId },
      relations: ['items'],
      order: { createdAt: 'DESC' },
      skip: (page - 1) * limit,
      take: limit,
    });

    return { items, total };
  }

  /**
   * 查询订单详情
   */
  async findOne(id: number, userId?: string): Promise<Order> {
    const where: any = { id };
    if (userId) {
      where.userId = userId;
    }

    const order = await this.orderRepository.findOne({
      where,
      relations: ['items', 'user'],
    });

    if (!order) {
      throw new NotFoundException('订单不存在');
    }

    return order;
  }

  /**
   * 根据订单号查询
   */
  async findByOrderNo(orderNo: string): Promise<Order> {
    const order = await this.orderRepository.findOne({
      where: { orderNo },
      relations: ['items', 'user'],
    });

    if (!order) {
      throw new NotFoundException('订单不存在');
    }

    return order;
  }

  /**
   * 取消订单
   * 只能取消待支付的订单
   */
  async cancel(id: number, userId: string, reason?: string): Promise<Order> {
    const order = await this.findOne(id, userId);

    if (order.status !== 'pending') {
      throw new BadRequestException('只能取消待支付的订单');
    }

    order.status = 'cancelled';
    order.cancelledAt = new Date();
    order.cancelReason = reason;

    return await this.orderRepository.save(order);
  }

  /**
   * 更新订单支付状态
   * 由支付回调调用
   */
  async updatePaymentStatus(
    orderNo: string,
    paymentData: {
      paymentMethod: 'alipay' | 'wechat';
      paymentNo: string;
      paidAt: Date;
    },
  ): Promise<Order> {
    const order = await this.findByOrderNo(orderNo);

    if (order.status !== 'pending') {
      throw new BadRequestException('订单状态不正确');
    }

    order.status = 'paid';
    order.paymentMethod = paymentData.paymentMethod;
    order.paymentNo = paymentData.paymentNo;
    order.paidAt = paymentData.paidAt;

    const updatedOrder = await this.orderRepository.save(order);

    // 支付成功后的业务逻辑
    await this.afterPaymentSuccess(updatedOrder);

    return updatedOrder;
  }

  /**
   * 支付成功后的处理
   * 1. 如果是会员订单，更新用户会员信息
   * 2. 如果是商品订单，增加下载权限
   * 3. 发送通知
   */
  private async afterPaymentSuccess(order: Order): Promise<void> {
    if (order.type === 'membership') {
      // 更新用户会员信息
      const item = order.items[0];

      if (!item.membershipMonths || !item.membershipLevel) {
        throw new BadRequestException('会员订单信息不完整');
      }

      await this.dataSource
        .createQueryBuilder()
        .update(User)
        .set({
          membershipLevel: item.membershipLevel,
          membershipExpireAt: dayjs()
            .add(item.membershipMonths, 'month')
            .toDate(),
        })
        .where('id = :userId', { userId: order.userId })
        .execute();
    }

    // TODO: 发送支付成功通知
    // TODO: 记录用户购买历史
    // TODO: 更新商品销量
  }

  /**
   * 自动关闭超时未支付的订单
   * 定时任务调用
   */
  async closeExpiredOrders(): Promise<number> {
    const result = await this.orderRepository
      .createQueryBuilder()
      .update(Order)
      .set({
        status: 'cancelled',
        cancelReason: '订单超时未支付',
        closedAt: new Date(),
      })
      .where('status = :status', { status: 'pending' })
      .andWhere('expireAt < :now', { now: new Date() })
      .execute();

    return result.affected || 0;
  }

  /**
   * 完成订单
   * 支付成功后一定时间自动完成，或用户手动确认
   */
  async complete(id: number): Promise<Order> {
    const order = await this.findOne(id);

    if (order.status !== 'paid') {
      throw new BadRequestException('订单状态不正确');
    }

    order.status = 'closed';
    order.closedAt = new Date();

    return await this.orderRepository.save(order);
  }

  /**
   * 退款
   */
  async refund(
    id: number,
    reason: string,
    refundAmount?: number,
  ): Promise<Order> {
    const order = await this.findOne(id);

    if (order.status !== 'paid' && order.status !== 'closed') {
      throw new BadRequestException('只能退款已支付或已完成的订单');
    }

    // 默认全额退款
    if (!refundAmount) {
      refundAmount = order.actualAmount;
    }

    // 验证退款金额
    if (refundAmount > order.actualAmount) {
      throw new BadRequestException('退款金额不能超过实付金额');
    }

    order.status = 'refunded';
    order.refundAmount = refundAmount;
    order.refundReason = reason;
    order.refundedAt = new Date();

    // TODO: 调用第三方支付平台退款接口

    return await this.orderRepository.save(order);
  }
}
